#ifndef _SMART_PRINT_
#define _SMART_PRINT_

#include <iostream>
#include <vector>
#include <string>

template<typename T>
class has_iterator {
    class false_type { char a[2]; };
    template<class S> static char check(typename S::const_iterator* i);
    template<class S> static false_type check(...);
public:
    static const bool value = sizeof(check<T>(0)) == sizeof(char);
};

template<bool> struct enable_if { typedef void it; };
template<> struct enable_if<false> {};

template<typename T>
typename enable_if<!has_iterator<T>::value>::it
smart_print(const T& arg, bool endl = true) {
    std::cout << arg;
    if (endl) {
        std::cout << std::endl;
    }
}

inline void smart_print(const std::string& arg, bool endl = true) {
    std::cout << "\"" << arg << "\"";
    if (endl) {
        std::cout << std::endl;
    }
}

template<typename T, typename S>
void smart_print(const std::pair<T, S>& arg, bool endl = true);

template<typename T>
typename enable_if<has_iterator<T>::value>::it
smart_print(const T& arg, bool endl = true) {
    std::cout << "[";
    for (typename T::const_iterator it = arg.begin(); it != arg.end(); ) {
        smart_print(*it, false);
        if (++it != arg.end()) {
            std::cout << ", ";
        }
    }
    std::cout << "]";
    if (endl) {
        std::cout << std::endl;
    }
}

template<typename T, typename S>
void smart_print(const std::pair<T, S>& arg, bool endl = true) {
    std::cout << "(";
    smart_print(arg.first, false);
    std::cout << ", ";
    smart_print(arg.second, false);
    std::cout << ")";
    if (endl) {
        std::cout << std::endl;
    }
}

#endif
